namespace TLang.Values.Primitives
{
    using System.Collections.Generic;
    using Values;
    using Ast;

    public class Add : PrimFun
    {
        public Add() : base("+", 2)
        {
            
        }


        public override Value Apply(List<Value> args, Node location)
        {
            Value v1 = args[0];
            Value v2 = args[1];

            if (v1 is IntValue a1 && v2 is IntValue b1)
            {
                return new IntValue(a1.Value + b1.Value);
            }
            if (v1 is FloatValue a2 && v2 is FloatValue b2)
            {
                return new FloatValue(a2.Value + b2.Value);
            }
            if (v1 is FloatValue a3 && v2 is IntValue b3)
            {
                return new FloatValue(a3.Value + b3.Value);
            }
            if (v1 is IntValue a4 && v2 is FloatValue b4)
            {
                return new FloatValue(a4.Value + b4.Value);
            }
            if (v1 is StringValue s1)
            {
                string s;
                if (v2 is StringValue r)
                {
                    s = r.Value;
                }
                else if (v2 is IntValue || v2 is FloatValue || v2 is BoolValue || v2 is TType)
                {
                    s = v2.ToString();
                }
                else
                {
                    throw Util.GeneralError(location, "incorrect argument types for +: " + v1 + ", " + v2);
                }
                return new StringValue(s1.Value + s);
            }
            if (v2 is StringValue s2)
            {
                string s;
                if (v1 is StringValue l)
                {
                    s = l.Value;
                }
                else if (v1 is IntValue || v1 is FloatValue || v1 is BoolValue || v1 is TType)
                {
                    s = v1.ToString();
                }
                else
                {
                    throw Util.GeneralError(location, "incorrect argument types for +: " + v1 + ", " + v2);
                }
                return new StringValue(s + s2.Value);
            }

            throw Util.GeneralError(location, "incorrect argument types for +: " + v1 + ", " + v2);
        }
    }
}